package com.inspur.edp.formserver.viewmodel.json.operation;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.inspur.edp.cef.designtime.api.json.SerializerUtils;
import com.inspur.edp.das.commonmodel.json.CommonModelNames;
import com.inspur.edp.formserver.viewmodel.action.viewmodelbase.ViewModelParActualValue;
import com.inspur.edp.formserver.viewmodel.action.viewmodelbase.ViewModelParameter;
import com.inspur.edp.formserver.viewmodel.common.VMCollectionParameterType;
import com.inspur.edp.formserver.viewmodel.common.VMParameterMode;
import com.inspur.edp.formserver.viewmodel.common.VMParameterType;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.viewmodel.exception.VoModelErrorCodes;
import com.inspur.edp.formserver.viewmodel.json.ViewModelJsonConst;
import java.io.IOException;

import static com.fasterxml.jackson.core.JsonToken.FIELD_NAME;
/**
 * The Json Deserializer Of View MOdel Action Parameter
 *
 * @ClassName: VmParameterDeserializer
 * @Author: Benjamin Gong
 * @Date: 2021/1/11 17:13
 * @Version: V1.0
 */
public abstract class VmParameterDeserializer<T extends ViewModelParameter> extends JsonDeserializer<T> {
    @Override
    public T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) {
        return deserializePara(jsonParser);
    }

    public final T deserializePara(JsonParser jsonParser) {
        T op = createVmPara();
        op.setParamDescription("");
        op.setParamCode("");
        op.setParamName("");
        op.setClassName("");
        SerializerUtils.readStartObject(jsonParser);
        while (jsonParser.getCurrentToken() == FIELD_NAME) {
            String propName = SerializerUtils.readPropertyName(jsonParser);
            readPropertyValue(op, propName, jsonParser);
        }
        SerializerUtils.readEndObject(jsonParser);
        return op;
    }

    private void readPropertyValue(ViewModelParameter para, String propName, JsonParser jsonParser) {
        switch (propName) {
            case CommonModelNames.ID:
                para.setID(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.ParamCode:
                para.setParamCode(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.ParamName:
                para.setParamName(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.ParameterType:
                para.setParameterType(SerializerUtils.readPropertyValue_Enum(jsonParser, VMParameterType.class, VMParameterType.values(), VMParameterType.String));
                break;
            case ViewModelJsonConst.Assembly:
                para.setAssembly(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.ClassName:
                para.setDotnetClassName(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.JavaClassName:
                para.setClassName(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.Mode:
                para.setMode(SerializerUtils.readPropertyValue_Enum(jsonParser, VMParameterMode.class, VMParameterMode.values(), VMParameterMode.IN));
                break;
            case ViewModelJsonConst.ParamDescription:
                para.setParamDescription(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.CollectionParameterType:
                para.setCollectionParameterType(SerializerUtils.readPropertyValue_Enum(jsonParser, VMCollectionParameterType.class, VMCollectionParameterType.values(), VMCollectionParameterType.None));
                break;
            case ViewModelJsonConst.ParamActualValue:
                if (SerializerUtils.readNullObject(jsonParser)) {
                    return;
                }
                para.setActualValue(SerializerUtils.readPropertyValue_Object(ViewModelParActualValue.class, jsonParser));
                //TODO: ?????? 此处参考了CustomizationInfo的反序列化, 有进一步完善的空间
                try {
                    jsonParser.nextToken();
                } catch (IOException e) {
                    throw new ViewModelException(e);
                }
                break;
            case ViewModelJsonConst.IsVoidReturnType:
                para.setVoidReturnType(SerializerUtils.readPropertyValue_boolean(jsonParser));
                break;
            default:
                if (!readExtendParaProperty(para, propName, jsonParser)) {
                    throw new ViewModelException(VoModelErrorCodes.GSP_VIEWOBJECT_MODEL_1049, null, propName);
                }
        }
    }

    protected boolean readExtendParaProperty(ViewModelParameter op, String propName, JsonParser jsonParser) {
        return false;
    }

    protected abstract T createVmPara();
}
